2017年搜狐内推 面试题——谈谈面试中的算法

在搜狐内推群,某同学接到面试电话,回忆了其中的几道算法题,有两道受到了群友的热烈讨论,因此写博客来分享下思路。

第一题:给你一个数组,其中有一个元素的个数大于数组总个数的一半,求出这个元素。

该同学的给出了方法一:先对数组排序,然后找到中间的那个数字,一定就是我们要找的元素。如果使用快速排序的话,该算法的平均时间复杂度为O(nlogn),空间复杂度为O(1)。

群友给的方法二:用HashMap 去解决,key存放元素,value存放个数,如果个数超过一般,输出这个元素。该算法时复杂度为O(n),空间复杂度为O(n)。

这里有一种时间复杂度为O(n),空间复杂度为O(1)的算法,主要思想如下:采用阵地攻守的思想:第一个数字作为第一个士兵,守阵地;count = 1;遇到相同元素,count++; 遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,到最后还留在阵地上的士兵,就是要找主元素。(ps:如果本题要求判断超过一半的元素是否存在,只要在遍历一次,记录剩余“士兵”的个数是否超过一半即可)。现在贴出java版算法:

public class Solution{
    public int majority Element(int[] num){
 
        int major=num[0], count = 1;
        for(int i=1; i<num.length;i++){
            if(count==0){
                count++;
                major=num[i];
            }else if(major==num[i]){
                count++;
            }else count--;
            
        }
        return major;
    }
}


 

该算法在《剑指offer》和leetcode中均有出现,所以有条件的话还是可以看看相关书籍,动手写写算法的。

 

第二题:给你一个数组,一个目标值sum,在里面寻找两个数使其和为target。

这也是一道很经典的算法题。

下面方法节选自《三十七章集锦by_July》。

方法一:直接穷举,时间复杂度O(n^2),显然是下下策。

方法二:对每个a[i],二分查找sum-a[i]是否也在原始序列中,每一次要查找的时间都要花费为O(logn),总的时间复杂度O(nlogn)。

方法三:有没有更好的办法呢?咱们可以依据上述思路2 的思想,a[i]在序列中,如果a[i]+a[k]=sum 的话,那么sum-a[i](a[k])也必然在序列中,举个例子,如下:原始序列:1、2、4、7、11、15 用输入数字15 减一下各个数,得到对应的序列为:14、13、11、8、4、0第一个数组以一指针i 从数组最左端开始向右扫描,第二个数组以一指针j 从数组最右端开始向左扫描,如果下面出现了和上面一样的数,即a[*i]=a[*j],就找出这俩个数来了。如上,i,j 最终在第一个,和第二个序列中找到了相同的数4 和11,所以符合条件的两个数,即为4+11=15。

具体操作方法为:要达到O(N)的复杂度,第一个数组以一指针i 从数组最左端开始向右扫描,第二个数组以一指针j 从数组最右端开始向左扫描,首先初始i 指向元素1,j 指向元素0,谁指的元素小,谁先移动,由于1(i)>0(j),所以i 不动,j 向左移动。然后j 移动到元素4 发现大于元素1,故而停止移动j,开始移动i,直到i 指向4,这时,i 指向的元素与j 指向的元素相等,故而判断4 是满足条件的第一个数;然后同时移动i,j 再进行判断,直到它们到达边界。

该方法利用提高空间复杂度来减少时间复杂度,要是对时间复杂度要求高,对空间不是很严格的话,也是一种不错的方法。

方法四:用hash表,给定a[i],根据映射查找sum-a[i]是否在数组中,时空都是O(n)。

方法五:如果数组有序,就可以利用两个指针i,j,各自指向数组的首尾两端,令 i=0,j=n-1,然后 i++,j--,逐次判断 a[i]+a[j]?=sum,如果某一刻 a[i]+a[j]>sum,则要想办法让sum 的值减小,所以此刻i 不动,j--,如果某一刻a[i]+a[j]<sum,则要想办法让sum 的值增大,所以此刻i++,j 不动。所以,数组无序的时候,时间复杂度最终为O(n*logn+n)=O(n*logn),若原数组是有序的,则不需要事先的排序,直接O(n)搞定,且空间复杂度还是O(1),此思路是相对于上述所有思路的一种改进。

 

说到这个题目,我想额外提一下,方法二中涉及二分查找,你会写二分查找吗?知道mid=(low+high)/2潜在的风险吗知道low<high条件可能会无法达到进入死循环吗?如果你不了解上述的任何一个情况,建议去查阅相关的博客。

 

从此次搜狐一面来看,主要是考察基础的经典的算法,所以学生在平时的学习重要注意夯实基础。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 好的,下面是对大数据面试题——spark面试题(一)的回答: 1. 什么是Spark?它与Hadoop有什么区别? Spark是一个快速、通用、可扩展的大数据处理引擎,它可以在内存进行数据处理,因此比Hadoop更快。与Hadoop相比,Spark的优点在于它可以在内存进行数据处理,因此速度更快,而且它支持更多的数据处理方式,例如流处理、图形处理等。 2. Spark的核心组件有哪些? Spark的核心组件包括Spark Core、Spark SQL、Spark Streaming、MLlib和GraphX。 3. 什么是RDD?它有哪些特点? RDD是Spark的一个基本概念,它代表一个不可变的分布式数据集合。RDD具有以下特点: - 可以在内存进行计算,因此速度快; - 支持多种操作,例如map、reduce、filter等; - 可以进行持久化,以便在后续计算重复使用。 4. Spark的map和flatMap有什么区别? map和flatMap都是RDD的转换操作,它们的区别在于: - map操作对每个元素进行转换,返回一个新的元素; - flatMap操作对每个元素进行转换,返回一个包含多个元素的序列。 5. 什么是Spark的shuffle操作? Spark的shuffle操作是指将数据重新分区的操作,它通常发生在reduce操作之前。Shuffle操作会将数据从多个节点上收集到一个节点上,然后重新分区,以便进行后续的计算。 6. Spark的cache和persist有什么区别? cache和persist都是将RDD持久化到内存,以便在后续计算重复使用。它们的区别在于: - cache操作默认将数据持久化到内存,而persist操作可以指定将数据持久化到内存、磁盘或者其他存储介质; - cache操作是persist操作的一种简化形式,它默认将数据持久化到内存,并且只能持久化到内存。 7. Spark的reduceByKey和groupByKey有什么区别? reduceByKey和groupByKey都是对键值对RDD进行操作的函数,它们的区别在于: - reduceByKey操作会在每个分区内先进行本地聚合,然后再进行全局聚合,因此效率更高; - groupByKey操作会将所有的键值对都进行网络传输,然后在一个节点上进行聚合,因此效率较低。 8. Spark的broadcast变量有什么作用? broadcast变量是一种只读的变量,它可以在所有节点上共享,以便在计算过程使用。使用broadcast变量可以避免在网络上传输大量的数据,从而提高计算效率。 9. 什么是Spark的checkpoint操作? Spark的checkpoint操作是将RDD持久化到磁盘上,以便在后续计算重复使用。与cache和persist不同的是,checkpoint操作会将数据持久化到磁盘上,以便在内存不足时可以从磁盘上恢复数据。 10. Spark的Task是什么? Task是Spark的一个基本概念,它代表一个可以在一个节点上执行的计算任务。Spark将一个RDD分成多个分区,每个分区对应一个Task,这些Task可以并行执行,以提高计算效率。 ### 回答2: 今天我们来讨论一下关于Spark大数据面试的一些常见问题。Spark是一种基于Hadoop的开源计算系统,它能够快速处理大规模数据,并且支持多种编程语言,包括Java、Scala和Python等。以下是一些Spark面试题及其答案: 1. Spark有哪几种部署模式? Spark有三种部署模式,分别是本地模式、集群模式和分布式模式。本地模式指的是在本地运行Spark应用程序,不需要连接到外部计算机。集群模式指的是单个Spark集群环境,它由一组Spark节点组成,可以在数据心或云运行。分布式模式指的是使用多个Spark集群并行处理大规模数据。 2. Spark和Hadoop的区别是什么? Spark和Hadoop都是处理大规模数据的工具,但它们有一些区别。首先,Spark处理数据速度快,因为它将数据存储在内存,而Hadoop则将数据存储在磁盘。其次,Spark支持更多的编程语言,包括Java、Scala和Python等,而Hadoop只支持Java。此外,Spark具有更好的机器学习和图形处理功能,可以更好地支持大规模数据分析。 3. Spark的RDD是什么? RDD是Spark重要的概念,全称为Resilient Distributed Dataset。它是一个不可变的分布式数据集合,可以分区存储在不同节点上,并且每个分区都可以在并行处理进行处理。RDD支持两种操作,即转化操作和行动操作。转化操作将一个RDD转换为另一个RDD,而行动操作返回一个结果或将结果输出至外部系统。 4. Spark的优化技术有哪些? Spark优化技术包括数据本地化、共享变量、宽依赖和窄依赖、缓存和持久化,以及数据分区等技术。数据本地化将数据存储在尽可能接近计算节点的位置,以减少网络传输的开销。共享变量将常用的变量通过广播或累加器的方式在节点共享,从而减少网络传输量。宽依赖和窄依赖指的是在转化操作RDD之间的依赖关系,窄依赖表示每个父分区最多与一个子分区有关联,而宽依赖则表示多个子分区可能与多个父分区关联。缓存和持久化技术可将RDD保存在内存,从而加速访问速度。数据分区可以将数据划分为较小的块进行并行处理。 5. Spark Streaming是什么? Spark Streaming是Spark的一个扩展模块,它支持实时数据流处理。Spark Streaming可以将实时数据流以微批次方式处理,每个批次的数据处理平均耗时只有几秒钟。Spark Streaming可以将数据存储在内存或磁盘,同时支持多种数据源和数据输出方式。 以上是关于Spark大数据面试题的一些回答,希望能够对大家有所帮助。如果你想深入学习Spark和大数据处理技术,可以考虑参加相关的培训课程或在线课程。 ### 回答3: Spark是一个分布式计算框架,它可以使大规模数据处理更加高效和便捷。因此,在企业招聘大数据领域的人才时,对Spark的技术能力要求越来越高。以下是Spark面试题的回答: 1. Spark有哪些组件? Spark框架由三个核心组件组成:Spark Core、Spark SQL和Spark Streaming。此外,还有Spark MLlib、Spark GraphX、Spark R等个别不同的子组件。 2. 什么是RDD?与Dataframe有什么区别? RDD(弹性分布式数据集)是Spark的核心数据抽象,是不可变的分布式对象集合。RDD可以从文件读取数据、从内存读取数据、并行修改数据等。而Dataframe和RDD类似,但是Dataframe更加强大,因为它是带有结构化的RDD。Dataframe在处理大规模结构化数据时非常有效和便捷。 3. Spark如何处理缺失数据? Spark提供了两种处理缺失数据的方法:第一种是使用DataFrame API的na函数,可以删除或替换缺失值;第二种是使用MLlib的Imputer类,可以将缺失值替换为均值或位数。 4. 什么是Spark的任务(task)? 一个任务是Spark作业的最小执行单位。Spark集群上的作业被划分为多个任务,这些任务可以并行执行。 5. Spark的shuffle操作是什么?它为什么是昂贵的? Spark的shuffle操作是将一组数据重新分配到不同计算节点上的操作。Shuffle操作可能会导致大量数据的磁盘写入、网络传输和数据重组,这些都是非常昂贵的操作。因此,它在Spark集群是一个相当昂贵的操作。 6. Spark的Partition有什么作用? Partition是Spark的数据划分单位。它可以将数据分成多个块并对每个块进行处理。Partition 可以提高 Spark 的并行度和运行效率,因为它可以将大规模数据分成多个小块,并在集群的多个计算节点上并行处理数据。 总而言之,Spark是大数据领域使用最广泛的计算引擎之一,其技术理念和应用场景非常广泛。对于求职者而言,掌握 Spark 的基本概念和技术特点,提高对 Spark 的理解和应用能力,将有助于更好地处理和分析大规模数据集。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值